#include "base.h"

// 毫秒级延时函数(不准确)
void delay_ms(uint32_t ms) {
    uint32_t i; 
    for (; ms > 0; ms--) {
        // 通过循环次数近似实现1ms延时（需根据实际CPU频率校准）
        for (i = SystemCoreClock / 7000; i > 0; i--) {
            __NOP(); // 空指令防止被优化
        }  
    }
}

volatile uint32_t systick_count = 0;  // 系统启动后的毫秒计数（需声明为 volatile）

void systick_init(void) {
    // 设置 SysTick 重装载值（以系统时钟频率计算）
    SysTick->LOAD = (SystemCoreClock / 1000) - 1;  // 1ms 中断一次
    
    // 配置 SysTick：使用处理器时钟、启用中断、启动定时器
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;
    
    // 启用 SysTick 中断（可选，部分芯片需额外配置 NVIC）
    NVIC_SetPriority(SysTick_IRQn, 0);  // 设置优先级
}

/**
 * @brief SysTick 中断服务函数（需在启动文件中声明）
 */
void SysTick_Handler(void)  {
    systick_count++;  // 毫秒计数加1
}

/**
 * @brief 获取系统启动后的毫秒数
 * @retval 从启动到当前的毫秒数
 */
uint32_t millis(void) {
    return systick_count;
}


static const int LED_PORTS[] = {GPIOE, GPIOD, GPIOG, GPIOA};
static const int LED_PINS[] = {GPIO_PIN_3, GPIO_PIN_7, GPIO_PIN_3, GPIO_PIN_5};

void led_init (led_t led) {
    int port = LED_PORTS[led];
    int pin = LED_PINS[led];

    gpio_mode_set(port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pin);
    gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin);
    gpio_bit_reset(port, pin);   // 初始熄灭
}

void led_set (led_t led, int on) {
    int port = LED_PORTS[led];
    int pin = LED_PINS[led];

   if (on) {
        gpio_bit_set(port, pin);     // 点亮LED
   } else {
        gpio_bit_reset(port, pin);   // 熄灭LED
   }       
}

int led_is_on (led_t led) {
    int port = LED_PORTS[led];
    int pin = LED_PINS[led];
    return gpio_input_bit_get(port, pin) == SET;
}


#define BUTTON_PIN GPIO_PIN_0
#define BUTTON_PORT GPIOA

void key_init (void) {
    // 配置按键引脚（输入，内部上拉）
    gpio_mode_set(BUTTON_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, BUTTON_PIN);
}

int key_pressed (void) {
    return gpio_input_bit_get(BUTTON_PORT, BUTTON_PIN) == SET;
}

#define BSP_USART_TX_RCU  RCU_GPIOA   // 串口TX的端口时钟
#define BSP_USART_RX_RCU  RCU_GPIOA   // 串口RX的端口时钟
#define BSP_USART_RCU     RCU_USART0  // 串口0的时钟

#define BSP_USART_TX_PORT GPIOA				// 串口TX的端口
#define BSP_USART_RX_PORT GPIOA				// 串口RX的端口
#define BSP_USART_AF 			GPIO_AF_7   // 串口0的复用功能
#define BSP_USART_TX_PIN  GPIO_PIN_9  // 串口TX的引脚
#define BSP_USART_RX_PIN  GPIO_PIN_10 // 串口RX的引脚

#define BSP_USART 				USART0      // 串口0

int uart_init (void)
{
  /* 开启时钟 */
	rcu_periph_clock_enable(BSP_USART_TX_RCU);   // 开启串口时钟
	rcu_periph_clock_enable(BSP_USART_RX_RCU);   // 开启端口时钟
	rcu_periph_clock_enable(BSP_USART_RCU);      // 开启端口时钟
	
	/* 配置GPIO复用功能 */
    gpio_af_set(BSP_USART_TX_PORT,BSP_USART_AF,BSP_USART_TX_PIN);	
	gpio_af_set(BSP_USART_RX_PORT,BSP_USART_AF,BSP_USART_RX_PIN);	
	
	/* 配置GPIO的模式 */
	/* 配置TX为复用模式 上拉模式 */
	gpio_mode_set(BSP_USART_TX_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_TX_PIN);
	/* 配置RX为复用模式 上拉模式 */
	gpio_mode_set(BSP_USART_RX_PORT, GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_RX_PIN);
	
	/* 配置TX为推挽输出 50MHZ */
	gpio_output_options_set(BSP_USART_TX_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_USART_TX_PIN);
	/* 配置RX为推挽输出 50MHZ */
	gpio_output_options_set(BSP_USART_RX_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART_RX_PIN);

	/* 配置串口的参数 */
	usart_deinit(BSP_USART);                                 // 复位串口
	usart_baudrate_set(BSP_USART,115200);                 // 设置波特率
	usart_parity_config(BSP_USART,USART_PM_NONE);            // 没有校验位
	usart_word_length_set(BSP_USART,USART_WL_8BIT);          // 8位数据位
	usart_stop_bit_set(BSP_USART,USART_STB_1BIT);     			 // 1位停止位

  /* 使能串口 */
	usart_enable(BSP_USART);                          			 // 使能串口
	usart_transmit_config(BSP_USART,USART_TRANSMIT_ENABLE);  // 使能串口发送
	usart_receive_config(BSP_USART,USART_RECEIVE_ENABLE);  // 使能串口发送
    return 0;
}

void uart_write (uint8_t ucch) {
	usart_data_transmit(BSP_USART,(uint8_t)ucch);							 // 发送数据
	while(RESET == usart_flag_get(BSP_USART,USART_FLAG_TBE));  // 等待发送数据缓冲区标志置位
}

int uart_available (void) {
    return usart_flag_get(BSP_USART, USART_FLAG_RBNE) == SET;
}

uint8_t uart_read (void) {
    return usart_data_receive(BSP_USART);
}


int stdout_putchar (int ch) {
    uart_write(ch);
    return ch;
}


// 初始化函数
void hardware_init(void) {
    // 启用外设时钟
    rcu_periph_clock_enable(RCU_GPIOA); 
    rcu_periph_clock_enable(RCU_GPIOB); 
    rcu_periph_clock_enable(RCU_GPIOC); 
    rcu_periph_clock_enable(RCU_GPIOD); 
    rcu_periph_clock_enable(RCU_GPIOE); 
    rcu_periph_clock_enable(RCU_GPIOF); 
    rcu_periph_clock_enable(RCU_GPIOG); 
    rcu_periph_clock_enable(RCU_GPIOH); 
    rcu_periph_clock_enable(RCU_GPIOI); 

    led_init(LED0);
    led_init(LED1);
    led_init(LED2);
    led_init(LED3);
    key_init();
    uart_init();

    // systick_init();
}

